package cn.yangliu.nacos.management.tools;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import javax.annotation.PostConstruct;

import cn.yangliu.nacos.comm.tools.TreeUtils;
import cn.yangliu.nacos.management.entity.sys.Authority;
import cn.yangliu.nacos.management.service.sys.AuthorityService;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

/**
 * The type of nacos.
 *
 * @author 问道于盲
 * @date 2020 -01-04
 */
@Component
public class AuthorityInitHelper {

    /**
     * current class's static member
     * The constant INIT_RESOURCE.
     */
    private static final String INIT_RESOURCE = "authority.xlsx";

    /**
     * current class instance's member.
     * The Authority service.
     */
    @Autowired
    private AuthorityService authorityService;

    /**
     * current class instance's member.
     * The Redis template.
     */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * current class's static member
     * The constant KEY.
     */
    private static final String KEY = "nacos:management:init";

    /**
     * Init.
     *
     * @throws IOException the io exception
     */
    @PostConstruct
    public void init() throws IOException {
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        if (StringUtils.isNotBlank(operations.get(KEY))) {
            return;
        }
        Resource resource = new ClassPathResource(INIT_RESOURCE);
        ExcelListener listener = new ExcelListener(authorityService);
        EasyExcel.read(resource.getInputStream(), AuthorityModel.class, listener).doReadAll();
        operations.set(KEY, "true");
    }

    /**
     * The interface Authority model.
     *
     * @author 问道于盲
     */
    @Data
    public static class AuthorityModel {

        /**
         * current class instance's member.
         * The Id.
         */
        @ExcelProperty("id")
        private String id;

        /**
         * current class instance's member.
         * The Name.
         */
        @ExcelProperty("name")
        private String name;

        /**
         * current class instance's member.
         * The Authority.
         */
        @ExcelProperty("authority")
        private String authority;

        /**
         * current class instance's member.
         * The Sort no.
         */
        @ExcelProperty("sort_no")
        private Integer sortNo;

        /**
         * current class instance's member.
         * The Button.
         */
        @ExcelProperty("button")
        private Boolean button;

        /**
         * current class instance's member.
         * The Parent id.
         */
        @ExcelProperty("parent_id")
        private String parentId;

        /**
         * current class instance's member.
         * The Remark.
         */
        @ExcelProperty("remark")
        private String remark;

        /**
         * current class instance's member.
         * The Children.
         */
        @ExcelIgnore
        private List<AuthorityModel> children = new ArrayList<>();

    }

    /**
     * The interface Excel listener.
     *
     * @author 问道于盲
     */
    public static class ExcelListener extends AnalysisEventListener<AuthorityModel> {

        /**
         * current class instance's member.
         * The Authority service.
         */
        private AuthorityService authorityService;

        /**
         * current class instance's member.
         * The List.
         */
        private List<AuthorityModel> list = new ArrayList<>();

        /**
         * Instantiates a new Excel listener.
         *
         * @param authorityService the authority service
         */
        ExcelListener(AuthorityService authorityService) {
            this.authorityService = authorityService;
        }

        /**
         * Invoke.
         *
         * @param line    the line
         * @param context the context
         */
        @Override
        public void invoke(AuthorityModel line, AnalysisContext context) {
            if (Objects.isNull(line.getParentId())) {
                line.setParentId("0");
            }
            list.add(line);
        }

        /**
         * Do after all analysed.
         *
         * @param context the context
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            AuthorityModel root = new AuthorityModel();
            root.setId("0");
            TreeUtils.createTree(list, root, "id", "parentId", "children");

            root.getChildren().forEach(model -> insert(model, 0L));
        }


        /**
         * Insert.
         *
         * @param root     the root
         * @param parentId the parent id
         */
        public void insert(AuthorityModel root, Long parentId) {
            try {
                Authority entity = new Authority();
                BeanUtils.copyProperties(root, entity);
                entity.setId(null);
                entity.setParentId(parentId);
                authorityService.save(entity);
                List<AuthorityModel> children = root.getChildren();

                for (AuthorityModel child : children) {
                    insert(child, entity.getId());
                }
            } catch (Exception e) {

            }

        }


    }
}
